package impl

import (
	"context"
	"github.com/sirupsen/logrus"
	"monoblog/common"
	"monoblog/common/register"
	"monoblog/domain/dao"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"monoblog/domain/service"
	"monoblog/util"
	"strings"
	"time"
)

func init() {
	register.RegisterInstance[service.UserService]("UserService", func() service.UserService {
		return &UserServiceImpl{
			userRepository:         dao.NewUserRepository(),
			userInterestRepository: dao.NewUserInterestRepository(),
		} // 返回唯一实例
	})
}

type UserServiceImpl struct {
	userRepository         *dao.UserRepository
	userInterestRepository *dao.UserInterestRepository
}

func (s *UserServiceImpl) AddUser(ctx context.Context, form dto.UserRegisterReqForm) error {
	// 创建用户对象
	webUser := &model.WebUser{
		Username: form.Username,
		Password: form.Password, //加密后的密码
		Phone:    form.Phone,
		Email:    form.Email,
		Nickname: form.Nickname,

		AvatarUrl: util.AvatarUrlGenerate(),

		Roles: []string{model.ROLE_USER},

		Status:     model.USER_NORMAL.Value(),
		CreateTime: time.Now(),
	}
	// 密码加密
	hashedPwd, err := util.PasswordEncrypt(form.Password)
	if err != nil {
		logrus.Errorf("[aid: %s] PasswordEncrypt err: %v", ctx.Value("aid"), err.Error())
		return err
	}
	webUser.Password = hashedPwd

	//保存user
	err = s.userRepository.Add(webUser)
	if err != nil {
		logrus.Errorf("[aid: %s] Add webUser failed: %v", ctx.Value("aid"), err.Error())
		return err
	}

	userInterest := &model.UserInterest{
		ID:           webUser.ID,
		UserId:       webUser.Username,
		FollowIds:    []string{},
		FansIds:      []string{},
		BlacklistIds: []string{},
	}
	_ = s.userInterestRepository.Add(userInterest)

	logrus.Infof("[aid: %s] Add webUser success.", ctx.Value("aid"))
	return nil
}

func (s *UserServiceImpl) ExistsByUserId(ctx context.Context, userId string) (bool, error) {
	if userId == "" {
		return false, nil
	}
	return s.userRepository.ExistsByUsername(userId)
}

func (s *UserServiceImpl) ExistsByPhoneOrEmail(ctx context.Context, phoneOrEmail string) (bool, error) {
	if phoneOrEmail == "" {
		return false, nil
	}
	if strings.Contains(phoneOrEmail, "@") {
		return s.userRepository.ExistsByEmail(phoneOrEmail)
	} else {
		return s.userRepository.ExistsByPhone(phoneOrEmail)
	}
}

func (s *UserServiceImpl) FindByUserId(ctx context.Context, userId string) (*model.WebUser, error) {
	return s.userRepository.FindByUserId(userId)
}

func (s *UserServiceImpl) FindFullByUserId(ctx context.Context, userId string) (*model.WebUser, error) {
	user, err := s.userRepository.FindByUserId(userId)
	if err != nil {
		logrus.Errorf("[aid: %s] FindByUserId err: %v", ctx.Value("aid"), err.Error())
		return nil, err
	}
	if interest, err := s.userInterestRepository.FindByUserId(userId); err == nil {
		user.Interest = interest
	}
	return user, nil
}

func (s *UserServiceImpl) FindPage(ctx context.Context, query dto.UserQuery) (*common.PageData[*model.WebUser], error) {
	list, count, err := s.userRepository.FindList(query)
	if err != nil {
		logrus.Errorf("[aid: %s] FindPage err: %v", ctx.Value("aid"), err.Error())
		return nil, err
	}
	pageData := &common.PageData[*model.WebUser]{}
	pageData.SetTotal(count, query.Limit())
	pageData.Records = list
	return pageData, nil
}

func (s *UserServiceImpl) FindInUserIds(ctx context.Context, userIds []string) ([]*model.WebUser, error) {
	if len(userIds) == 0 {
		return []*model.WebUser{}, nil
	}

	query := dto.UserQuery{
		UserIds: userIds,
	}
	list, _, err := s.userRepository.FindList(query)
	return list, err
}
